package com.ly.spring.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * Company 源辰信息
 *
 * @author navy
 * @date 2024/11/7
 * Email haijunzhou@hnit.edu.cn
 */
@Component
@Aspect
public class MyAspect {

    @Before("execution(* com.ly..*Mapper.*(..))")
    // 直接用方法参数注入对象=>接口注入
    public void before(JoinPoint jp){
        System.out.println("方法签名 jp.getSignature() = " + jp.getSignature());
        System.out.println("参数数组 jp.getArgs() = " + Arrays.toString(jp.getArgs()));
        System.out.println(".........前置拦截.........");
    }

    // 切点方法
    @Pointcut("execution(* com.ly..*Mapper.*(..))")
    public void myPointcut(){}

    @After("myPointcut()")
    public void after(JoinPoint jp){
        System.out.println(".........后置拦截.........");
    }

    @AfterReturning(value = "myPointcut()", returning = "ret")
    public void afterReturning(Object ret){
        // 可以获取业务的返回值
        System.out.println("业务的返回值 ret = " + ret);
        System.out.println(".........返回拦截.........");
    }

    @AfterThrowing(value="myPointcut()", throwing = "e")
    public void afterThrowing(JoinPoint jp, Throwable e){
        System.out.println("业务方法的异常 ret = " + e);
        System.out.println(".........异常拦截.........");
    }

    @Around("myPointcut()")
    public Object around(ProceedingJoinPoint jp){
        // 环绕增强业务方法是手动执行
        try{
            System.out.println("--------- 环绕增强: 前置------------");
            long begin = System.currentTimeMillis();
            Object ret = jp.proceed();
            long end = System.currentTimeMillis();
            System.out.printf(jp.getSignature() + " 共耗时: " + (end - begin) + " 毫秒");
            System.out.println("--------- 环绕增强: 返回------------");
            // 环绕增强的方法返回值 => 业务方法的返回值
            return ret;
        } catch (Throwable e){
            System.out.println("--------- 环绕增强: 异常------------");
            throw new RuntimeException("业务方法出现异常",e);
        } finally {
            System.out.println("--------- 环绕增强: 后置------------");
        }
    }

    /**
     *
     * try{
     *      前置增强
     *     ------------> 业务方法
     *      返回增强
     * } catch (Exception e){
     *      异常增强
     * } finally {
     *      后置增强
     * }
     *
     */
}
